﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using System.Windows.Controls;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Text.RegularExpressions;
using System.ComponentModel;

namespace FarpacHelper
{
    #region Album Toolstring
    public class ToolCollection
    {
        public int test = 50;
        public ObservableCollection<Tool> ToolstringDiagram { get; set; }
        public ObservableCollection<Tool> ToolsCollection { get; set; }

        public ToolCollection(IEnumerable<Tool> InitTools)
        {
            this.ToolstringDiagram = new ObservableCollection<Tool>();
            this.ToolsCollection = new ObservableCollection<Tool>(InitTools);
        }

        public ToolCollection()
        {
            this.ToolstringDiagram = new ObservableCollection<Tool>();

            this.ToolsCollection = new ObservableCollection<Tool>();

            this.ToolsCollection.Add(new Tool("Bull Plug 2\"", "2in", "1234", "0000", new Uri("ImagesToolstring\\BullPlug.png", UriKind.Relative), 0, 1, 30, 30, description: "Bull Plug 2 inches", length: "8cm"));
            this.ToolsCollection.Add(new Tool("Cable Head", "1.5625in", "1234", "0000", new Uri("ImagesToolstring\\CableHead.png", UriKind.Relative), 0, 1, 30, 30, description: "Cable Head Small Size Fishing Neck", length: "35cm"));
            this.ToolsCollection.Add(new Tool("Diode Sub 2\"", "2in", "1234", "0000", new Uri("ImagesToolstring\\DiodeSub.png", UriKind.Relative), 0, 1, 30, 30, description: "Selective Fire Diode Sub 2 inches", length: "6cm"));
            this.ToolsCollection.Add(new Tool("Knuckle Joint 1.6\"", "1.5625in", "1234", "0000", new Uri("ImagesToolstring\\KnuckleJoint.png", UriKind.Relative), 0, 1, 30, 30, description: "Knuckle Joint 1-9/16 inches", length: "30cm"));
            this.ToolsCollection.Add(new Tool("Knuckle Joint 2\"", "2in", "1234", "0000", new Uri("ImagesToolstring\\KnuckleJoint2.png", UriKind.Relative), 0, 1, 30, 30, description: "Knuckle Joint 2 inches", length: "30cm"));
            this.ToolsCollection.Add(new Tool("Tandem Sub 2\"", "2in", "1234", "0000", new Uri("ImagesToolstring\\Tandem.png", UriKind.Relative), 0, 1, 30, 30, description: "Tandem Sub for Gun 2 inches", length: "6cm"));
            this.ToolsCollection.Add(new Tool("Shoot CCL 2\"", "2in", "1234", "0000", new Uri("ImagesToolstring\\CCL-Perf_color.png", UriKind.Relative), 0, 1, 30, 30, description: "Bull Plug 2 inches", length: "36cm"));
            this.ToolsCollection.Add(new Tool("Pressure CAP 2\"", "2in", "1234", "0000", new Uri("ImagesToolstring\\Cap-Go.png", UriKind.Relative), 0, 1, 30, 30, description: "Pressure Cap Go Connection 2 inches", length: "5cm"));
            this.ToolsCollection.Add(new Tool("Arm Sleeve 2\"", "2in", "1234", "0000", new Uri("ImagesToolstring\\Arming Sleeve_color1.png", UriKind.Relative), 0, 1, 30, 30, description: "Arming Sleeve 2 inches", length: "30cm"));
            this.ToolsCollection.Add(new Tool("xOver 1.6\"", "1.5625in", "1234", "0000", new Uri("ImagesToolstring\\Contact Sub_color.png", UriKind.Relative), 0, 1, 30, 30, description: "Cross-Over Sub 1-9/16 inches", length: "2.5cm"));
            this.ToolsCollection.Add(new Tool("Fire Adapter 2\"", "2in", "1234", "0000", new Uri("ImagesToolstring\\Firing Adapter_color.png", UriKind.Relative), 0, 1, 30, 30, description: "Firing Adapter 1-9/16 to 2 inches", length: "25cm"));
            this.ToolsCollection.Add(new Tool("Firing Head 1.6\"", "1.5625in", "1234", "0000", new Uri("ImagesToolstring\\Firing Head_color.png", UriKind.Relative), 0, 1, 30, 30, description: "Firing Head 1-9/16 inches", length: "7cm"));
            this.ToolsCollection.Add(new Tool("Gun Plug 2\"", "2in", "1234", "0000", new Uri("ImagesToolstring\\Gun Bull Plug_color.png", UriKind.Relative), 0, 1, 30, 30, description: "Gun Bull Plug 2 inches", length: "8cm"));
            this.ToolsCollection.Add(new Tool("GUN 2\"", "2in", "1234", "0000", new Uri("ImagesToolstring\\GUN_color4.png", UriKind.Relative), 0, 1, 30, 30, description: "Gun 2 inches Millenium", length: "100cm"));
            this.ToolsCollection.Add(new Tool("Junk Basket 2\"", "2in", "1234", "0000", new Uri("ImagesToolstring\\J-Basket_color1.png", UriKind.Relative), 0, 1, 30, 30, description: "Junk Basket 2 inches", length: "137cm"));
            this.ToolsCollection.Add(new Tool("Knuckle Joint 2.5\"", "2.5in", "1234", "0000", new Uri("ImagesToolstring\\Pkj-color1.png", UriKind.Relative), 0, 1, 30, 30, description: "Knuckle Joint 2-1/2 inches", length: "30cm"));
            this.ToolsCollection.Add(new Tool("Roller 2\"", "2in", "1234", "0000", new Uri("ImagesToolstring\\Roller_color.png", UriKind.Relative), 0, 1, 30, 30, description: "Non-Conductor Roller 2 inches", length: "34cm"));
            this.ToolsCollection.Add(new Tool("Spang Jar 2\"", "2in", "1234", "0000", new Uri("ImagesToolstring\\spang_jar.png", UriKind.Relative), 0, 1, 30, 30, description: "Spang Jar 2 inches", length: "196cm"));
            this.ToolsCollection.Add(new Tool("Tandem Sub 1.6\"", "1.5625in", "1234", "0000", new Uri("ImagesToolstring\\Tandem Sub_color.png", UriKind.Relative), 0, 1, 30, 30, description: "Tandem Sub 1-9/16 inches", length: "6cm"));
            this.ToolsCollection.Add(new Tool("Weight Bar 2\"", "2in", "1234", "0000", new Uri("ImagesToolstring\\W-BAR_color1.png", UriKind.Relative), 0, 1, 30, 30, description: "Weight Bar Lead Non-Conductor 2 inches", length: "200cm"));

        }
    }

    public class Tool : INotifyPropertyChanged, ICloneable
    {
        enum LengthUnit { NA, IN, FT, CM, DM, M, FT_S, IN_S };
        enum WeightUnit { NA, KG, LBS };
        static string[] LENGTH_UNIT = { "", "in", "ft", "cm", "dm", "m", "\'", "\"" };
        static double[] CMper_UNIT = { 0, 2.54, 30.48, 1, 10, 100, 30.48, 2.54 };
        static double[] INper_UNIT = { 0, 1, 12, 1 / CMperIN, 10 / CMperIN, 100 / CMperIN, 12, 1 };
        static string[] WEIGHT_UNIT = { "", "kg", "lb" };
        static double[] LBper_UNIT = { 0, LBperKG, 1 };
        static double[] KGper_UNIT = { 0, 1, 1 / LBperKG };

        const double CMperFT = 30.48;
        const double CMperM = 100;
        const double LBperKG = 2.20462262;
        const double CMperIN = 2.54;

        private double LengthFromString(LengthUnit unit, string length)
        {
            double len = 0;

            string unit_pattern = string.Empty;
            foreach (string s in LENGTH_UNIT)
            {
                unit_pattern += "|" + s;
            }
            unit_pattern = unit_pattern.Remove(0, 2); // Remove first double || character
            unit_pattern = "(" + unit_pattern + ")";

            Match match = Regex.Match(length.ToLower(), @"^(.*[0-9])[\s_-]*" + unit_pattern); // eg : 12.5in, 12.5 in, 12.5_in, 12.5-in

            if (match.Success)
            {
                try { len = Convert.ToDouble(match.Groups[1].Value); }
                catch (Exception e) { MessageBox.Show("Cannot convert ToDoubleLength : " + length, "Check your NUMBER INPUT again !"); return 0; }
                string s = match.Groups[2].Value;

                for (int i = 0; i < LENGTH_UNIT.Length; i++)
                {
                    if (s == LENGTH_UNIT[i])
                    {
                        switch (unit)
                        {
                            case LengthUnit.CM: len *= CMper_UNIT[i]; break;
                            case LengthUnit.DM: len *= CMper_UNIT[i] / 10; break;
                            case LengthUnit.FT: len *= INper_UNIT[i] / 12; break;
                            case LengthUnit.FT_S: len *= INper_UNIT[i] / 12; break;
                            case LengthUnit.IN: len *= INper_UNIT[i]; break;
                            case LengthUnit.IN_S: len *= INper_UNIT[i]; break;
                            case LengthUnit.M: len *= CMper_UNIT[i] / 100; break;
                            case LengthUnit.NA: len = 0; break;
                            default: len = 0; break;
                        }
                    }
                }
            }
            else { MessageBox.Show("LengthFromString : No Unit Recognize : " + length, "Check your NUMBER INPUT again !"); return 0; }

            return len;
        }

        private double WeightFromString(WeightUnit unit, string weight)
        {
            double weg = 0;

            string unit_pattern = string.Empty;
            foreach (string s in WEIGHT_UNIT)
            {
                unit_pattern += "|" + s;
            }
            unit_pattern = unit_pattern.Remove(0, 2); // Remove first double || character
            unit_pattern = "(" + unit_pattern + ")";

            Match match = Regex.Match(weight.ToLower(), @"^(.*[0-9])[\s_-]*" + unit_pattern); // eg : 12.5kg, 12.5 kg, 12.5_kg, 12.5-kg

            if (match.Success)
            {
                try { weg = Convert.ToDouble(match.Groups[1].Value); }
                catch (Exception e) { MessageBox.Show("Cannot convert ToDoubleWeight : " + weight, "Check your NUMBER INPUT again !"); return 0; }
                string s = match.Groups[2].Value;

                for (int i = 0; i < WEIGHT_UNIT.Length; i++)
                {
                    if (s == WEIGHT_UNIT[i])
                    {
                        switch (unit)
                        {
                            case WeightUnit.KG: weg *= KGper_UNIT[i]; break;
                            case WeightUnit.LBS: weg *= LBper_UNIT[i]; break;
                            case WeightUnit.NA: weg = 0; break;
                            default: weg = 0; break;
                        }
                    }
                }
            }
            else { MessageBox.Show("WeightFromString : No Unit Recognize : " + weight, "Check your NUMBER INPUT again !"); return 0; }

            return weg;
        }

        private double[] MultiplyArray(double[] input, double multiplier)
        {
            double[] temp = new double[input.Length];
            for (int i = 0; i < input.Length; i++)
            {
                temp[i] = input[i] * multiplier;
            }
            return temp;
        }

        public Uri ImageLocation { get; set; }
        /// <summary>
        /// the % X coordinator in ImageTool that we start counting as Tool Diameter
        /// </summary>
        public double Xbegin { get; set; }
        /// <summary>
        /// the % X coordinator in ImageTool that we finish counting as Tool Diameter
        /// </summary>
        public double Xend { get; set; }
        int renderWidth;
        public int RenderWidth
        {
            get { return renderWidth; }
            set { if (value != renderWidth) { renderWidth = value; OnPropertyChanged("RenderWidth"); } }
        }
        int renderHeight;
        public int RenderHeight
        {
            get { return renderHeight; }
            set { if (value != renderHeight) { renderHeight = value; OnPropertyChanged("RenderHeight"); } }
        }

        public string Model { get; set; }
        public string Description { get; set; }

        public string Length { get; set; }
        public double LengthCM
        {
            get
            {
                return LengthFromString(LengthUnit.CM, Length);
            }
            set
            {
                Length = value.ToString() + "cm";
            }
        }
        public double LengthFT
        {
            get
            {
                return LengthFromString(LengthUnit.FT, Length);
            }
            set
            {
                Length = value.ToString() + "ft";
            }
        }
        public string Weight { get; set; }
        public double WeightKG
        {
            get
            {
                return WeightFromString(WeightUnit.KG, Weight);
            }
            set
            {
                Weight = value.ToString() + "kg";
            }
        }
        public double WeightLB
        {
            get
            {
                return WeightFromString(WeightUnit.LBS, Weight);
            }
            set
            {
                Weight = value.ToString() + "lbs";
            }
        }
        public string Diameter { get; set; }
        public double DiameterCM
        {
            get
            {
                return LengthFromString(LengthUnit.CM, Diameter);
            }
            set
            {
                Diameter = value.ToString() + "cm";
            }
        }
        public double DiameterIN
        {
            get
            {
                return LengthFromString(LengthUnit.IN, Diameter);
            }
            set
            {
                Diameter = value.ToString() + "in";
            }
        }
        public double Voltage { get; set; }
        public double Current { get; set; }

        public string Name { get; set; }
        public string Size { get; set; }
        public string Serial { get; set; }
        public string SAP { get; set; }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="name"></param>
        /// <param name="size">Inches Diameter in this format : 2in or 2.0"</param>
        /// <param name="serial">Tool Serial</param>
        /// <param name="sap">Tool SAP</param>
        /// <param name="imageLocation">Uri Path</param>
        /// <param name="xbegin"></param>
        /// <param name="xend"></param>
        /// <param name="renderwidth"></param>
        /// <param name="renderheight"></param>
        /// <param name="model">2", 1-9/16", 2-1/2"</param>
        /// <param name="description"></param>
        /// <param name="length">centimeter</param>
        /// <param name="weight">lbs</param>
        /// <param name="diameter">inches</param>
        /// <param name="voltage">volt</param>
        /// <param name="current">ampere</param>
        public Tool(string name, string size, string serial, string sap, Uri imageLocation, double xbegin, double xend, int renderwidth, int renderheight,
            string model = "N/A", string description = "N/A", string length = "1cm", string weight = "1.5lbs", string diameter = "2in", double voltage = 1.5, double current = 1)
        {
            // Will Use
            this.Name = name;
            this.Size = size;
            this.Serial = serial;
            this.SAP = sap;
            this.ImageLocation = imageLocation;

            // To Match with Warrior
            this.Model = model;
            this.Description = description;
            this.Length = length;
            this.Weight = weight;
            this.Diameter = diameter;
            /*if (this.Size.Contains("in") | this.Size.Contains("\""))
                this.Diameter = this.Size.Substring(0, this.Size.IndexOfAny(new Char[] { 'i', '\"' }));
            else
                this.Diameter = diameter;*/

            this.Voltage = voltage;
            this.Current = current;

            // For Scale Purpose
            this.Xbegin = xbegin;
            this.Xend = xend;
            this.RenderWidth = renderwidth;
            this.RenderHeight = renderheight;
        }

        #region INotifyPropertyChanged Members
        public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;

        // Create the OnPropertyChanged method to raise the event 
        protected void OnPropertyChanged(string name)
        {
            System.ComponentModel.PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new System.ComponentModel.PropertyChangedEventArgs(name));
            }
        }
        #endregion

        #region ICloneable Members
        public object Clone()
        {
            return MemberwiseClone();
        }
        #endregion
    }
    #endregion
}
